﻿#ifndef _F7813AA0_F2F1_4F24_B7DD_455532813E8D
#define _F7813AA0_F2F1_4F24_B7DD_455532813E8D

#include "depends/incfile.h"
#include "depends/uz.h"

namespace x2lib
{
    class ZipUtil
    {
    public:
        struct ItemZipped
        {
            int index;
            char szName[256];
            uint32_t zSize;
            uint32_t uzSize;
        };

        // ZipUtil作为对象使用时，仅支持压缩文件对象的操作

        ZipUtil(const char* pszZipFile/*已存在的zip文件，或欲新建的zip文件*/, const char* pszPwd = nullptr);
        ZipUtil(char* pZipData, int nZipData, const char* pszPwd = nullptr);
        virtual ~ZipUtil();


        // xktesla@2021-10-23 23:28:28 经尝试，无法在压缩或解压缩失败时100%在pnDataout保存真实所需内存大小，因此统一不返回真实所需大小
        // 仅当返回true才表示成功，否则失败原因未知
        // 建议令*pnDataout满足：(*pnDataout>0x1000) ? *pnDataout : 0x1000

        static uint32_t GetUnCompressSize(const char* pszInFile, const char* pszPwd = nullptr);
        static uint32_t GetUnCompressSize(char* pData, int nData, const char* pszPwd = nullptr);
        static uint32_t GuessCompressSize(int nData/*压缩前大小*/);

        // 对一个目录打包，输出到指定位置
        static bool Compress(const char* pszInFolder, const char* pszOutFile, const char* pszPwd = nullptr);
        static bool Compress(const char* pszInFolder, char* pDataout, int* pnDataout, const char* pszPwd = nullptr);

        // 对一块内存压缩，返回压缩后的内存
        static bool Compress(char* pData, int nData, char* pDataout, int* pnDataout, const char* pszPwd = nullptr, const char* pszName = "mem");

        // 对一个压缩包进行解压
        static bool UnCompress(const char* pszInFile, const char* pszOutFolder, const char* pszPwd = nullptr);
        static bool UnCompress(const char* pszInFile, char* pDataout, int* pnDataout, const char* pszPwd = nullptr);

        // 对一个内存进行解压
        static bool UnCompress(char* pData, int nData, const char* pszOutFolder, const char* pszPwd = nullptr);
        static bool UnCompress(char* pData, int nData, char* pDataout, int* pnDataout, const char* pszPwd = nullptr);

        uint32_t GetItemCount();
        ItemZipped GetItemInfo(int index);
        ItemZipped GetItemInfo(const char* pszItemFile);

        // 向压缩包添加一个文件，isCover暂未实现
        bool AppendItem(const char* pszInFile, const char* pszItemFile, bool isCover = true);
        bool AppendItem(char* pData, int nData, const char* pszItemFile, bool isCover = true);
        
        // 从压缩包删除一个文件
        bool DeleteItem(const char* pszItemFile);

        // 从压缩包解压一个文件
        bool ExtractItem(const char* pszItemFile, const char* pszOutFile);
        bool ExtractItem(const char* pszItemFile, char* pDataout, int* pnDataout);
        bool ExtractItem(int index, const char* pszOutFile);
        bool ExtractItem(int index, char* pDataout, int* pnDataout);

        bool OutputAsFile(const char* pszZipFile);
        bool OutoutAsData(char* pDataout, int* pnDataout);
        bool GetCompressSize();

    private:
        static bool unCompress(unzip::HZIP hZip, const char* pszOutFolder);
        static bool unCompress(unzip::HZIP hZip, char* pDataout, int* pnDataout);
        static bool getZipMem(unzip::HZIP hZip, char* pDataout, int* pnDataout);
        bool reOpenZip(char* pZip, uint32_t nZip);

        unzip::HZIP m_hZip;
        char m_szZipFile[512];
        char m_szZipFileTemp[512];
        char* m_pZipData;
        char* m_pZipDataTemp;
        char m_szPwd[64];
        bool m_fileMode;
    };
}

#endif

